POI2013 Where is the one

POI2013 Where is the one

题目大意:

有一个1到n的排列,并且给你两个函数:

f(i,j,d):返回bool,表示d|(P[i]-P[j])是否成立。

g(i,j):返回P[i]是否比P[j]大.

你可以调用无限次f(只要不TLE),以及尽量少的g。

最终来确定元素1的位置。

题解:

我们可以发现,f函数可以用来判断,是否存在一个P[j]与P[i]的差值为d。

由于是一个排列,因而满足二分的性质:

以1为基准点,可以二分一个差值,并看看是否存在一个数与P[1]差值为d。

这样可以找到一个与P[1]相差最大的值的位置。(元素1或元素n)

再找到与它相差n-1的元素的位置。(元素1或元素n中的另一个)

最后调用一次g函数判断哪一个更小,那个就是元素1。

(注意特判n=1的情况)

Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include "cgdzlib.h"
#include <assert.h>
using namespace std;
int id1,id2;
bool judge(int cur){
for(int i=2;i<=n;i++)
if(f(1,i,cur)){id1=i;return true;}
return false;
}
int main(){
n=inicjuj();
if(n==1){
odpowiedz(1);
return 0;
}
int L=1,R=n-1;
while(L<=R){
int mid=L+R>>1;
if(judge(mid))L=mid+1;
else R=mid-1;
}
for(int i=1;i<=n;i++){
if(i==id1)continue;
if(f(id1,i,n-1))id2=i;
}
if(g(id1,id2))odpowiedz(id2);
else odpowiedz(id1);
return 0;
}
分享到 评论